package com.kob.matchingsystem.utils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 用户池
 */
@Component
public class MatchingPool extends Thread {

    //多个线程公用的，要上锁
    private static List<Player> players = new ArrayList<>();

    //这里不用线程安全的类，因为我们自己会手动加锁把不安全的变为安全的
    private static ReentrantLock lock = new ReentrantLock();

    private static RestTemplate restTemplate;
    private final static String startGameUrl = "http://127.0.0.1:3000/pk/start/game/";

    @Autowired
    public void setRestTemplate(RestTemplate restTemplate) {
        MatchingPool.restTemplate = restTemplate;
    }

    //添加玩家
    public void addPlayer(Integer user_id, Integer rating, Integer botId) {
        lock.lock();
        try {
            players.add(new Player(user_id, rating, botId, 0));
        } finally {
            lock.unlock();
        }
    }

    //删除玩家
    public void removePlayer(Integer user_id) {
        lock.lock();
        try {
            ArrayList<Player> newPlayers = new ArrayList<>();
            for (Player player : players) {
                if (player.getUserId() != user_id)
                    newPlayers.add(player);
            }
            players = newPlayers;
        } finally {
            lock.unlock();
        }
    }

    //将所有玩家等待时间加1
    private void increaseWaitTime() {
        for (Player player : players) {
            player.setWaitingTime(player.getWaitingTime() + 1);
        }
    }

    //判断两名玩家是否匹配
    //判断分差能不能小于等于a与b的等待时间的最小值*10
    private boolean checkMatched(Player a, Player b) {
        int ratingDifference = Math.abs(a.getRating() - b.getRating());
        int waitDifference = Math.abs(a.getWaitingTime() - b.getWaitingTime());
        return ratingDifference <= waitDifference * 10;
    }

    //返回匹配结果
    private void sendResult(Player a, Player b) {
        System.out.println("send result: " + a + " " + b);
        MultiValueMap<String, String> data = new LinkedMultiValueMap<>();
        data.add("a_id", a.getUserId().toString());
        data.add("a_bot_id", a.getBotId().toString());
        data.add("b_id", b.getUserId().toString());
        data.add("b_bot_id", b.getBotId().toString());
        restTemplate.postForObject(startGameUrl, data, String.class);
    }

    //尝试匹配所有玩家
    private void matchPlayers() {
        System.out.println("match players: " + players.toString());
        boolean[] used = new boolean[players.size()];
        for (int i = 0; i < players.size(); i++) {
            if (used[i]) continue;
            for (int j = i + 1; j < players.size(); j++) {
                if (used[j]) continue;
                //判断是否匹配
                if (checkMatched(players.get(i), players.get(j))) {
                    used[i] = used[j] = true;
                    sendResult(players.get(i), players.get(j));
                    break;
                }
            }
        }
        //上面如果匹配成功,还要把用户playerA、playerB是删除
        ArrayList<Player> newPlayers = new ArrayList<>();
        for (int i = 0; i < players.size(); i++) {
            if (!used[i])
                newPlayers.add(players.get(i));
        }
        players = newPlayers;
    }

    @Override
    public void run() {
        while (true)        //一直匹配,所以MatchingPool一直都会执行
        {
            try {
                Thread.sleep(1000);
                lock.lock();
                try {
                    increaseWaitTime();
                    matchPlayers();
                } finally {
                    lock.unlock();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
                break;
            }
        }
    }
}
